/******************************************
 * Nombre del archivo: At_Funcion.java
 * Universidad del Valle de Guatemala
 * Curso: Algoritmos y Estructura de Datos
 * Autores:
 *      * Martín Guzmán     08041
 *      * David Hsieh       08225
 *      * Eduardo Mejicano  08058
 *      * Kevin Sánchez     08302
 * Fecha: 24 de agosto de 2009
 * Descripción:
*******************************************/

import java.util.LinkedList;
import java.util.ArrayList;

public class At_Funcion {
    private String nombre="";
    private At_Lista lista_funcion;
    private String lista_funcion_str;
    private At_Lista_Literal lista_literal_funcion;

    public At_Funcion(String nombre,At_Lista_Literal lista_literal_funcion,String lista_funcion_str){
        this.nombre =nombre;
        this.lista_literal_funcion=lista_literal_funcion;
        this.lista_funcion_str=lista_funcion_str;
    }

    /*****************************************
     * Método: getNombre
     * Autor: Martín Guzmán
     * Uso: obtener el nombre de una función.
     * Retorno: String nombre
     *****************************************/
    public String getNombre() {
        return nombre;
    }

    
    /*****************************************
     * Método: replace
     * Autor: Martín Guzmán
     * Uso: reemplazar los parámetros de la
     *      función para evaluar.
     * Retorno: String. Cambia la función que
     *          hay que evaluar.
     *****************************************/
    public String replace(String lista_a_cambiar) {
        String result="";
        result=lista_funcion_str;

        ArrayList<String> nueva_lista = Arreglar_texto(lista_a_cambiar);

        for(int i=0;i<nueva_lista.size();i++)
        {
            if(nueva_lista.get(i).compareToIgnoreCase("'")==0){
                nueva_lista.remove(i);
                String copia = nueva_lista.get(i);
                nueva_lista.remove(i);
                nueva_lista.add("',"+copia);
            }
            //System.out.println("."+nueva_lista.get(i)+".");
        }

        //System.out.println("Lista que se cambia: "+lista_a_cambiar.texto_lista);
        //System.out.println(result);//TODO quitar esto //debuguear

        if(this.lista_literal_funcion.lista.size()==nueva_lista.size()){
            //System.out.println("tamaños iguales");
            for(int i=0;i<nueva_lista.size();i++){
                Atomo temp = null;
                String a= nueva_lista.get(i);
                if (a.startsWith("(") && a.endsWith(")")){
                    temp = new At_Lista(a.substring(2,a.length()-1));
                }
                else{
                    temp = new At_Variable(a);
                }
                //System.out.println("antes de meter a la función: "+a);
                String resultado= temp.Obtener_valor();
                if(resultado.startsWith("(")){
                    resultado="',"+resultado;
                }
                //System.out.println(lista_literal_funcion.lista.get(i)+".bla");
                result=result.replaceAll(","+(lista_literal_funcion.lista.get(i)),","+resultado);
            }

            //System.out.println(result);//TODO quitar esto //debuguear
            return result;
        }
        System.out.println("Error. The funtion "+this.nombre+" needs "+lista_literal_funcion.lista.size()+((lista_literal_funcion.lista.size()==1)?" parameter":" parameters"));//TODO quitar esto //debuguear
        return "";
    }



    /*****************************************
     * Método: getLista_funcion
     * Autor: Martín Guzmán
     * Uso: obtener la lista a evaluar.
     * Retorno: At_Lista lista de la función
     ***********************nombre******************/
    public At_Lista getLista_funcion() {
        return lista_funcion;
    }

    /*****************************************
     * Método: getLista_literal_funcion
     * Autor: Martín Guzmán
     * Uso: obtener las variables con las que puede contar.
     * Retorno: String nombre
     *****************************************/
    public At_Lista_Literal getLista_literal_funcion() {
        return lista_literal_funcion;
    }

    /*****************************************
     * Método: getLista_funcion_str
     * Autor: Martín Guzmán
     * Uso: obtener el texto para formar la lista.
     * Retorno: String lista_funcion_str
     *****************************************/
    public String getLista_funcion_str() {
        return lista_funcion_str;
    }

    /*****************************************
     * Método: Obtener_valor
     * Autor: Martín Guzmán
     * Uso: Obtiene el valor de una expresión
     * Retorno: valor de la evaluación de la
     *          lista de la función.
     *****************************************/
    public String Obtener_valor(String val){
        At_Lista temporal = new At_Lista(val);
        String a=temporal.Obtener_valor();
        return a;
    }

    /*****************************************
     * Método: Arreglar_texto
     * Autor: Martín Guzmán
     * Uso: divide en átomos el texto
     * Retorno: guarda los átomos en una lista.
     *****************************************/
    public ArrayList<String> Arreglar_texto(String texto_lista){
        //texto_lista.replaceAll("',", "'");
        String[] temporal=texto_lista.split(",");

        //pasar a una lista el arreglo de strings
        ArrayList<String> temporal_lista = new ArrayList<String>();
        for(int i=0;i<temporal.length;i++)
        {
            temporal_lista.add(temporal[i]);
        }
        //***********************************
        ArrayList<String> temporal_a_agregar = new ArrayList<String>();
        for(int i=0;i<temporal_lista.size();i++)
        {
            String sub_cadena=temporal_lista.get(i);
            if (temporal_lista.get(i).startsWith("("))//agrupar hasta que se cierre este paréntesis
            {
                int parentesis=1;
                int posicion=i;
                for(int j=i+1;j<temporal_lista.size();j++){
                    if(temporal[j].contains(")"))
                        parentesis--;
                    if (parentesis==0){
                        posicion=j;
                        break;
                    }
                    if(temporal[j].startsWith("("))
                        parentesis++;

                }
                sub_cadena="";
                //System.out.println("i"+i+" j:"+posicion);//TODO quitar esto
                for(int a=i;a<=posicion;a++){
                   sub_cadena+=","+temporal_lista.get(a);
                }
                sub_cadena=sub_cadena.substring(1, sub_cadena.length());//para quitarle la última ","
                i=posicion;
            }
            //System.out.println("Sub-cadena: ."+sub_cadena+".");//TODO quitar esto
            temporal_a_agregar.add(sub_cadena);
        }
        return temporal_a_agregar;
    }
}
